package dao

import (
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"context"
	"errors"
	"gorm.io/gen/field"
	"gorm.io/gorm/clause"

	"gorm.io/gorm"
	"mini-app/config/mysql"
	"mini-app/internal/dal"
	"mini-app/internal/models"
)

type PuppetUserRepo struct {
	query *dal.Query
}

func getCommonQuery(in any) *dal.Query {
	if db, ok := in.(*gorm.DB); ok {
		return dal.Use(db)
	}
	ctx := in.(context.Context)
	return dal.Use(mysql.NewDB().WithContext(ctx))
}

func NewPuppetUserRepo(in any) *PuppetUserRepo {
	return &PuppetUserRepo{query: getCommonQuery(in)}
}

func (p PuppetUserRepo) fmtFilter(ctx context.Context, f IPuppetUserFilter) dal.IPuppetUserDo {
	tx := p.query.PuppetUser.WithContext(ctx)
	tx = f.fmtFilter(ctx, tx, p.query)
	return tx
}

// 查询
func (p PuppetUserRepo) FindOneById(ctx context.Context, id int64) (*models.PuppetUser, error) {
	return p.query.PuppetUser.WithContext(ctx).Where(p.query.PuppetUser.ID.Eq(id)).First()
}

func (p PuppetUserRepo) FindOneByFilter(ctx context.Context, f IPuppetUserFilter) (*models.PuppetUser, error) {
	tx := p.fmtFilter(ctx, f)

	rc, err := tx.First()
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}

		logx.Error(ctx, "PuppetUser.FindOneByFilter", logx.Any("err", err))
		return nil, errors.Join(errors.New("查询失败"), err)
	}

	return rc, nil
}

// 更新

func (p PuppetUserRepo) UpdateById(ctx context.Context, data *models.PuppetUser) error {
	if data.ID <= 0 {
		return errors.New("id不能为0")
	}

	_, err := p.query.PuppetUser.WithContext(ctx).Where(p.query.PuppetUser.ID.Eq(data.ID)).Updates(data)
	return err
}

// 通过筛选器进行更新，但是建议都用id方式进行update
func (p PuppetUserRepo) UpdateByFilter(ctx context.Context, f IPuppetUserFilter, data *models.PuppetUser) error {
	tx := p.fmtFilter(ctx, f)
	_, err := tx.Updates(data)
	return err
}

/* 例子
// 只更新 NickName 和 Gender 字段，即使其他字段有值也不更新
repo.UpdateColByFilter(ctx, filter, &models.PuppetUser{
    NickName: "新昵称",
    Gender: 1,
    WinCount: 100, // 这个字段不会被更新
},
p.query.PuppetUser.NickName,  // 强类型字段
p.query.PuppetUser.Gender,    // 强类型字段
)
*/
// 只更新指定列
func (p PuppetUserRepo) UpdateColByFilter(ctx context.Context, f IPuppetUserFilter, data *models.PuppetUser, columns ...field.Expr) error {
	tx := p.fmtFilter(ctx, f)
	_, err := tx.Select(columns...).Updates(data)
	return err
}

/*
// UpdateAssignByFilter - 直接赋值更新
repo.UpdateAssignByFilter(ctx, filter,
    p.query.PuppetUser.NickName.Value("新昵称"),
    p.query.PuppetUser.Gender.Value(0), // 支持零值
)
*/
// 指定列0值也会更新，未指定列非0值也会更新
func (p PuppetUserRepo) UpdateAssignByFilter(ctx context.Context, f IPuppetUserFilter, assigns ...field.AssignExpr) error {
	tx := p.fmtFilter(ctx, f)
	_, err := tx.UpdateSimple(assigns...)
	return err
}

// 增加
func (p PuppetUserRepo) Insert(ctx context.Context, data *models.PuppetUser) error {
	data.ID, _ = helper.UUID{}.Int64()
	return p.query.PuppetUser.WithContext(ctx).Create(data)
}

func (p PuppetUserRepo) MultiInsert(ctx context.Context, data []*models.PuppetUser) error {
	return p.query.PuppetUser.WithContext(ctx).Clauses(clause.OnConflict{UpdateAll: true}).Create(data...)
}

// 删除
func (p PuppetUserRepo) DeleteByFilter(ctx context.Context, f IPuppetUserFilter) error {
	tx := p.fmtFilter(ctx, f)
	_, err := tx.Delete()
	return err
}

func (p PuppetUserRepo) DeleteById(ctx context.Context, id int64) error {
	if id <= 0 {
		return errors.New("id不能为0")
	}

	assign := p.query.PuppetUser.Deleted.Value(true)
	_, err := p.query.PuppetUser.WithContext(ctx).Where(p.query.PuppetUser.ID.Eq(id)).UpdateSimple(assign)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}

		logx.Error(ctx, "PuppetUserRepo.DeleteById", logx.Any("err", err))
		return err
	}
	//_, err := p.query.PuppetUser.WithContext(ctx).Where(p.query.PuppetUser.ID.Eq(id)).Delete()
	return err
}

// 列表

//func (p PuppetUserRepo) FindByFilter(ctx context.Context, f *PuppetUserFilter, page *helper.PageInfo) ([]*models.PuppetUser, error) {
//	tx := p.fmtFilter(ctx, f)
//	result, _, err := tx.FindByPage(int(page.GetOffset()), int(page.GetLimit()))
//	return result, err
//}

func (p PuppetUserRepo) ListByFilter(ctx context.Context, f IPuppetUserFilter, page *helper.PageInfo) ([]*models.PuppetUser, int64, error) {
	list, count, err := p.fmtFilter(ctx, f).FindByPage(int(page.GetOffset()), int(page.GetLimit()))
	return list, count, err
}

// 未提供exsit函数，使用Count函数判断返回个数来达到同样目的
func (p PuppetUserRepo) CountByFilter(ctx context.Context, f IPuppetUserFilter) (int64, error) {
	tx := p.fmtFilter(ctx, f)
	return tx.Count()
}
